#include "rs232device.h"
#include <chrono>
#include <QTime>
#include <QCoreApplication>
static constexpr std::chrono::seconds kWriteTimeout = std::chrono::seconds{5};

RS232Device::RS232Device(QObject *parent)
    : Device{parent}
    , m_serial(new QSerialPort(this))
    , m_timer(new QTimer())
    , m_nPort(1)
    , m_eBaud(QSerialPort::Baud115200)
    , m_eParity(QSerialPort::NoParity)
    , m_eDatabits(QSerialPort::Data8)
    , m_eStopbits(QSerialPort::OneStop)
{
    connect(m_serial, &QSerialPort::errorOccurred, this, &RS232Device::handleError);
    connect(m_timer, &QTimer::timeout, this, &RS232Device::handleWriteTimeout);
    m_timer->setSingleShot(true);
    connect(m_serial, &QSerialPort::readyRead, this, &RS232Device::readData);
    connect(m_serial, &QSerialPort::bytesWritten, this, &RS232Device::handleBytesWritten);
}

Device* RS232Device::clone(Device* pDevice){
    m_strID = pDevice->getStrID();

    m_nPort = ((RS232Device*)pDevice)->GetSPort();
    m_eBaud = ((RS232Device*)pDevice)->GetBaud();
    m_eParity = ((RS232Device*)pDevice)->GetParity();
    m_eDatabits = ((RS232Device*)pDevice)->GetDatabits();
    m_eStopbits = ((RS232Device*)pDevice)->GetStopbits();
    m_eFlowcontrol = ((RS232Device*)pDevice)->GetFlowControl();
    return this;
}

RS232Device::~RS232Device(){
    uninitDevice();
}

int RS232Device::GetSPort() const
{
    return m_nPort;
}

void RS232Device::SetSPort(int port)
{
    m_nPort = port;
}

QSerialPort::BaudRate RS232Device::GetBaud() const
{
    return m_eBaud;
}

void RS232Device::SetBaud(QSerialPort::BaudRate baud)
{
    m_eBaud = baud;
}

QSerialPort::Parity RS232Device::GetParity() const
{
    return m_eParity;
}

void RS232Device::SetParity(QSerialPort::Parity parity)
{
    m_eParity = parity;
}

QSerialPort::DataBits RS232Device::GetDatabits() const
{
    return m_eDatabits;
}

void RS232Device::SetDatabits(QSerialPort::DataBits databits)
{
    m_eDatabits = databits;
}

QSerialPort::StopBits RS232Device::GetStopbits() const
{
    return m_eStopbits;
}

void RS232Device::SetStopbits(QSerialPort::StopBits stopbits)
{
    m_eStopbits = stopbits;
}

QSerialPort::FlowControl RS232Device::GetFlowControl() const{
    return m_eFlowcontrol;
}

void RS232Device::SetFlowControl(QSerialPort::FlowControl flowControl){
    m_eFlowcontrol = flowControl;
}

int RS232Device::initDevice(){
    qDebug() << "初始话RS232Device...";
    return openSerialPort();
}

void RS232Device::uninitDevice(){
    closeSerialPort();
}

QString RS232Device::getClassName(){
    return this->metaObject()->className();
}

void RS232Device::writeXML(QXmlStreamWriter& writer){
    writer.writeStartElement("RS232Device");
    writer.writeAttribute(QStringLiteral("id"),m_strID);

    writer.writeTextElement("port", QString::number(m_nPort));
    writer.writeTextElement("baud", QString::number(m_eBaud));
    writer.writeTextElement("parity", QString::number(m_eParity));
    writer.writeTextElement("databits", QString::number(m_eDatabits));
    writer.writeTextElement("stopbits", QString::number(m_eStopbits));
    writer.writeEndElement();
}
// 有点问题
void RS232Device::readFromXML(QXmlStreamReader& reader){
    QXmlStreamAttributes attributes = reader.attributes();
    if(attributes.hasAttribute("id")) {
        m_strID = attributes.value("id").toString();
    }

    QXmlStreamReader::TokenType token = reader.readNext();
    while (!(reader.tokenType() == QXmlStreamReader::EndElement &&
             reader.name() == QStringLiteral("RS232Device"))) {

        if (reader.name() == QStringLiteral("port")) {
            m_nPort = reader.readElementText().toInt();
        }else if (reader.name() == QStringLiteral("baud")) {
            m_eBaud = (QSerialPort::BaudRate)(reader.readElementText().toInt());
        }else if (reader.name() == QStringLiteral("parity")) {
            m_eParity = (QSerialPort::Parity)(reader.readElementText().toInt());
        }else if (reader.name() == QStringLiteral("databits")) {
            m_eDatabits = (QSerialPort::DataBits)(reader.readElementText().toInt());
        }else if (reader.name() == QStringLiteral("stopbits")) {
            m_eStopbits = (QSerialPort::StopBits)(reader.readElementText().toInt());
        }

        reader.readNext();
    }
}

int RS232Device::openSerialPort()
{
    m_serial->setPortName(QString("COM%1").arg(m_nPort));
    m_serial->setBaudRate(m_eBaud);
    m_serial->setDataBits(static_cast<QSerialPort::DataBits>(m_eDatabits));
    m_serial->setParity(static_cast<QSerialPort::Parity>(m_eParity));
    m_serial->setStopBits(static_cast<QSerialPort::StopBits>(m_eStopbits));
    m_serial->setFlowControl(QSerialPort::NoFlowControl);
    if (m_serial->open(QIODevice::ReadWrite)) {
        qDebug() << QString("串口打开成功!");
        return 0;
    } else {
        qDebug() << QString("Error : %1.").arg(m_serial->errorString());
        qDebug() << ("Open error!");
        return -1;
    }
}

void RS232Device::closeSerialPort()
{
    if (m_serial->isOpen())
        m_serial->close();
}

void RS232Device::writeData(const QVariant &data){
    QByteArray bytes = data.toByteArray();
    const qint64 written = m_serial->write(bytes);
    m_serial->waitForBytesWritten();
}

void RS232Device::readData()
{
    const QByteArray data = m_serial->readAll();
    qDebug() << data;
}

void RS232Device::handleError(QSerialPort::SerialPortError error)
{
    if (error == QSerialPort::ResourceError) {
        qDebug() << QString("Critical Error: %1").arg(m_serial->errorString());
        closeSerialPort();
    }
}

void RS232Device::handleBytesWritten(qint64 bytes)
{
    m_bytesToWrite -= bytes;
    /*if (m_bytesToWrite == 0)
        m_timer->stop();*/
}

void RS232Device::handleWriteTimeout()
{
    const QString error = tr("Write operation timed out for port %1.\n"
                             "Error: %2").arg(m_serial->portName(),
                                   m_serial->errorString());
    qDebug() << (error);
}

